/*
 * Copyright© 2003-2019 浙江汇信科技有限公司, All Rights Reserved.
 */
package com.icinfo.cloud.provider.punish.ucase.casemain.service.impl;

import com.icinfo.cloud.common.core.config.CfRedisRepository;
import com.icinfo.cloud.provider.common.constant.Constant;
import com.icinfo.cloud.provider.common.exception.BusinessException;
import com.icinfo.cloud.provider.logs.mapper.LogsCaseDocumentSerialRecordMapper;
import com.icinfo.cloud.provider.logs.model.LogsCaseDocumentSerialRecord;
import com.icinfo.cloud.provider.logs.service.ILogsCaseDocumentSerialRecordService;
import com.icinfo.cloud.provider.punish.config.mapper.SysDepartParamMapper;
import com.icinfo.cloud.provider.punish.config.model.SysDepartParam;
import com.icinfo.cloud.provider.punish.ucase.casemain.dto.CaseDocumentNumberSerialDto;
import com.icinfo.cloud.provider.punish.ucase.casemain.mapper.CaseDocumentNumberSerialMapper;
import com.icinfo.cloud.provider.punish.ucase.casemain.model.CaseDocumentNumberSerial;
import com.icinfo.cloud.provider.punish.ucase.casemain.service.ICaseDocumentNumberSerialService;
import com.icinfo.cloud.workflow.common.util.IdUtil;
import com.icinfo.framework.core.service.support.MyBatisServiceSupport;
import com.icinfo.framework.mybatis.mapper.entity.Example;
import com.icinfo.framework.tools.utils.StringUtils;
import lombok.extern.slf4j.Slf4j;
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.ObjectUtils;

import javax.annotation.Resource;
import java.time.LocalDateTime;
import java.util.List;

/**
 * 描述: 文号序列记录 case_document_number_serial 对应的Service接口实现类.<br>
 *
 * @author framework generator
 * @date 2022年03月14日
 */
@Slf4j
@Service
@Transactional(rollbackFor = {Exception.class,Error.class})
public class CaseDocumentNumberSerialServiceImpl extends MyBatisServiceSupport implements ICaseDocumentNumberSerialService {

    @Autowired
    private CaseDocumentNumberSerialMapper caseDocumentNumberSerialMapper;
    @Autowired
    private ILogsCaseDocumentSerialRecordService logsCaseDocumentSerialRecordService;

    private static final String LOCKPREFIX = "DOCNUM:";

    @Resource
    private RedissonClient redisson;
    @Resource
    private SysDepartParamMapper sysDepartParamMapper;
    @Resource
    private CfRedisRepository cfRedisRepository;
    @Resource
    private LogsCaseDocumentSerialRecordMapper logsCaseDocumentSerialRecordMapper;


    //@Override
    public Long getNumber_Old(String documentCatalogCode, String caseOrgCode,String lineCode){
        CaseDocumentNumberSerial param = new CaseDocumentNumberSerialDto();
        param.setDocumentCatalogCode(documentCatalogCode);
        param.setAreaCode(caseOrgCode);
        param.setLineCode(lineCode);
        List<CaseDocumentNumberSerial> caseDocumentNumberSerial = caseDocumentNumberSerialMapper.select(param);
        if (caseDocumentNumberSerial.isEmpty()){
            //新增文书序列
            CaseDocumentNumberSerial newCaseSerial = new CaseDocumentNumberSerial();
            newCaseSerial.setSerial(1L);
            newCaseSerial.setId(StringUtils.uuid());
            newCaseSerial.setDocumentCatalogCode(documentCatalogCode);
            newCaseSerial.setAreaCode(caseOrgCode);
            newCaseSerial.setLineCode(lineCode);
            caseDocumentNumberSerialMapper.insert(newCaseSerial);
            return 1L;
        }
        // 更新逻辑
        CaseDocumentNumberSerial upDateSerial = caseDocumentNumberSerialMapper.selectForLock(documentCatalogCode, caseOrgCode,"",lineCode,"upcase.case_document_number_serial");
        upDateSerial.setSerial(upDateSerial.getSerial() + 1);
        upDateSerial.setAreaCode(caseOrgCode);
        upDateSerial.setLineCode(lineCode);
        caseDocumentNumberSerialMapper.updateByPrimaryKeySelective(upDateSerial);
        Long serial = upDateSerial.getSerial();
        log.info("@@@@@@@获取到的文号:" + serial);
        return serial;
    }


    /**
     * 描述： 获取序号(加锁)
     *
     * @author: zhengqiang
     * @date: 2022/10/18
     * @param: documentCatalogCode
     * @param: caseOrgCode
     * @param: lineCode
     * @return {@link Long}
     **/
    @Transactional(propagation = Propagation.REQUIRES_NEW)
    @Override
    public Long getNumber(String busiId, String sourceType, String documentCatalogCode, String caseOrgCode,String caseDeptCode,String lineCode, String year) {
        //判断是否配置二级单位参数配置
        if(!StringUtils.isBlank(caseDeptCode)) {
            Example example = new Example(SysDepartParam.class);
            example.createCriteria().andEqualTo("orgCode", caseOrgCode).andEqualTo("deptCode", caseDeptCode).andEqualTo("isDeleted", Constant.STRING_0);
            List<SysDepartParam> sysDepartParamList = sysDepartParamMapper.selectByExample(example);
            if (ObjectUtils.isEmpty(sysDepartParamList)) {
                //如果不存在二级配置存在 取deptCode
                caseDeptCode = "";
            }
        }
        String lockKey = LOCKPREFIX + caseOrgCode + ":" +caseDeptCode+ documentCatalogCode;
        RLock lock = redisson.getLock(lockKey);
        try {
            lock.lock();

            //如果是立案审批表 优化从redis队列中获取
            /*if(DocumentKindEnum.DOC_KIND_LASPB.equals("")){
                String lfpNum = cfRedisRepository.leftPop(lockKey);
                if(StringUtils.isNotBlank(lfpNum)){
                    return Long.valueOf(lfpNum);
                }
            }*/

            /*CaseDocumentNumberSerial param = new CaseDocumentNumberSerialDto();
            param.setDocumentCatalogCode(documentCatalogCode);
            param.setAreaCode(caseOrgCode);
            param.setLineCode(lineCode);
            if(!StringUtils.isBlank(caseDeptCode)){
                param.setDeptCode(caseDeptCode);
            }*/
            //如果是2022就走老的表，如果是2023就走新的表
            String serailTable = "";
            int yearNow = LocalDateTime.now().getYear();
            String currentYear = "〔" + yearNow + "〕";
            if("〔2022〕".equals(year)){
                serailTable = "upcase.case_document_number_serial";
            }else if("〔2023〕".equals(year)){
                serailTable = "upcase.case_document_number_serial_2023";
            }else if(currentYear.equals(year)){
                serailTable = "upcase.case_document_number_serial_"+yearNow;
            }
            CaseDocumentNumberSerial caseDocumentNumberSerial = caseDocumentNumberSerialMapper.selectForLock(documentCatalogCode,caseOrgCode,caseDeptCode,lineCode,serailTable);
            Long serial = 1L;
            Long excepSeral = null;
            LogsCaseDocumentSerialRecord logsCaseDocumentSerialRecord = new LogsCaseDocumentSerialRecord();
            logsCaseDocumentSerialRecord.setDocumentCatalogCode(documentCatalogCode);
            logsCaseDocumentSerialRecord.setLineCode(lineCode);
            logsCaseDocumentSerialRecord.setDeptCode(caseDeptCode);
            logsCaseDocumentSerialRecord.setOrgCode(caseOrgCode);
            logsCaseDocumentSerialRecord.setYear(year);
            logsCaseDocumentSerialRecord.setSourceType(sourceType);

            if (ObjectUtils.isEmpty(caseDocumentNumberSerial)) {
                //新增文书序列
               /* CaseDocumentNumberSerial newCaseSerial = new CaseDocumentNumberSerial();
                newCaseSerial.setSerial(1L);
                newCaseSerial.setId(StringUtils.uuid());
                newCaseSerial.setDocumentCatalogCode(documentCatalogCode);
                newCaseSerial.setAreaCode(caseOrgCode);
                newCaseSerial.setLineCode(lineCode);
                newCaseSerial.setDeptCode(caseDeptCode);*/
                caseDocumentNumberSerialMapper.insertCaseDocumentNumberSerialWithLock(documentCatalogCode,caseOrgCode,caseDeptCode,lineCode,StringUtils.uuid(),serailTable);
            }else{
                //优先拿序列记录表里的异常记录，没有异常记录再拿最新的序列
                //if("A02210000001".equals(lineCode) || "A09410000001".equals(lineCode)){//先综合执法进行验证
                    excepSeral = logsCaseDocumentSerialRecordService.getLogsCaseDocumentSerialRecordException(logsCaseDocumentSerialRecord);
                //}
                if(excepSeral!=null){
                    serial = excepSeral;
                }else {
                    serial = caseDocumentNumberSerial.getSerial() + 1;
                    caseDocumentNumberSerialMapper.updateSerialWithLock(documentCatalogCode,caseOrgCode,caseDeptCode,lineCode,serailTable,serial);
                }
                //log.info("@@@@@@@获取到的文号:" + serial + "，所属部门：【" + caseOrgCode + caseDeptCode + "】");
            }

            if(excepSeral!=null){//如果是从异常池里获取的，要更新异常池记录
                logsCaseDocumentSerialRecord.setSerial(excepSeral);
                logsCaseDocumentSerialRecord.setBusiId(busiId);
                logsCaseDocumentSerialRecordService.modLogsCaseDocumentSerialExcepToNormal(logsCaseDocumentSerialRecord);
            }else {//如果不是异常池获取的，则新增正常的日志记录
                logsCaseDocumentSerialRecord.setId(IdUtil.createUid());
                logsCaseDocumentSerialRecord.setBusiId(busiId);
                logsCaseDocumentSerialRecord.setSerial(serial);
                logsCaseDocumentSerialRecord.setSerialTable(serailTable);
                logsCaseDocumentSerialRecord.setIfException("0");
                logsCaseDocumentSerialRecordService.saveLogsCaseDocumentSerialRecord(logsCaseDocumentSerialRecord);
            }

            return serial;
        } catch (Exception e) {
            throw new BusinessException("获取文号失败");
        } finally {
            if (lock.isLocked() && lock.isHeldByCurrentThread()) {
                lock.unlock();
            }
        }
    }

    /**
     * 描述： 保存异常文书序号日志
     *
     * @author: zhengqiang
     * @date: 2023/12/7
     * @return {@link }
     **/
    @Transactional(rollbackFor = {Error.class, Exception.class})
    @Override
    public int saveLogsCaseDocumentSerialRecordException(LogsCaseDocumentSerialRecord logsCaseDocumentSerialRecord) {
        //更新文书序号日志记录为异常
        int i = logsCaseDocumentSerialRecordMapper.updateLogsCaseDocumentSerialRecordException(logsCaseDocumentSerialRecord);
        if (i == 0) {
            //更新条数为0, 则新增异常日志记录
            String caseOrgCode = logsCaseDocumentSerialRecord.getOrgCode();
            String caseDeptCode = logsCaseDocumentSerialRecord.getDeptCode();
            String year = logsCaseDocumentSerialRecord.getYear();
            //判断是否配置二级单位参数配置
            if(!StringUtils.isBlank(caseDeptCode)) {
                Example example = new Example(SysDepartParam.class);
                example.createCriteria().andEqualTo("orgCode", caseOrgCode).andEqualTo("deptCode", caseDeptCode).andEqualTo("isDeleted", Constant.STRING_0);
                List<SysDepartParam> sysDepartParamList = sysDepartParamMapper.selectByExample(example);
                if (ObjectUtils.isEmpty(sysDepartParamList)) {
                    //如果不存在二级配置存在 取deptCode
                    caseDeptCode = "";
                }
            }
            //如果是2022就走老的表，如果是2023就走新的表
            String serailTable = "";
            if("〔2022〕".equals(year)){
                serailTable = "upcase.case_document_number_serial";
            }else if("〔2023〕".equals(year)){
                serailTable = "upcase.case_document_number_serial_2023";
            }
            logsCaseDocumentSerialRecord.setDeptCode(caseDeptCode);
            logsCaseDocumentSerialRecord.setYear(year);
            logsCaseDocumentSerialRecord.setId(IdUtil.createUid());
            logsCaseDocumentSerialRecord.setSerialTable(serailTable);
            logsCaseDocumentSerialRecord.setIfException("1");
            i = logsCaseDocumentSerialRecordMapper.insert(logsCaseDocumentSerialRecord);
        }
        return i;
    }
}
